//
// Created by hps on 24-3-26.
//

#include "EditorWindow.h"

namespace hps {
EditorWindow::EditorWindow(QWidget *parent) {
    m_editorTabMgr = new QTabWidget();
    m_layout = new QVBoxLayout(this);
    m_firstWord = new QLabel();
    m_firstWordFrame = new QFrame();
    m_firstWordLayout = new QVBoxLayout();
    m_tabWidgetMoreButton = new hps::TabWidgetMoreButton();
    m_tabWidgetButtonsFrame = new QFrame();
    m_tabWidgetButtonsLayout = new QHBoxLayout();
    m_tabWidgetMoreMenu = new QMenu();
    m_closeAllTabAction = new QAction();
    m_setFontSizeAction = new QAction();
    m_editorTextEditChoose = new QComboBox();
    m_tabWidgetEditButton = new hps::MarkDownEditButton();
    m_tabWidgetPreviewAndButton = new hps::MarkDownPreviewAndEditButton();
    m_tabWidgetPreviewButton = new hps::MarkDownPreviewButton();
    init();
    setEditorUi();
    rspFunc();
}

void EditorWindow::init() {
    m_layout->setContentsMargins(0, 0, 0, 0);
    m_layout->setSpacing(0);
    m_firstWord->setText("创建笔记，开启记录之旅!");
    m_firstWord->setFont(CONFIG()->getEditorFirstWordFont());
    m_firstWord->setPalette(CONFIG()->getEditorFirstWordPalette());
    m_firstWordLayout->setContentsMargins(0, 0, 0, 0);
    m_editorTabMgr->setTabsClosable(true);
    m_editorTabMgr->setMovable(true);
    m_tabWidgetButtonsLayout->setContentsMargins(0, 5, 10, 5);
    m_tabWidgetButtonsLayout->setSpacing(3);
    m_closeAllTabAction->setText("关闭所有文件");
    m_setFontSizeAction->setText("设置字体大小");
    m_editorTabMgr->setContentsMargins(0, 0, 0, 0);
}

void EditorWindow::setEditorUi() {
    showFirstPage();

    m_tabWidgetButtonsLayout->insertWidget(0, m_tabWidgetEditButton);
    m_tabWidgetButtonsLayout->insertWidget(1, m_tabWidgetPreviewAndButton);
    m_tabWidgetButtonsLayout->insertWidget(2, m_tabWidgetPreviewButton);
    m_tabWidgetButtonsLayout->insertWidget(3, m_tabWidgetMoreButton);
    m_tabWidgetButtonsFrame->setLayout(m_tabWidgetButtonsLayout);
    m_editorTabMgr->setCornerWidget(m_tabWidgetButtonsFrame, Qt::TopRightCorner);

    m_tabWidgetMoreMenu->addAction(m_closeAllTabAction);
    m_tabWidgetMoreMenu->addAction(m_setFontSizeAction);
}

void EditorWindow::showFirstPage() {
    m_firstWordFrame->setLayout(m_firstWordLayout);
    m_firstWordLayout->addWidget(m_firstWord);

    m_layout->addWidget(m_firstWordFrame);
    m_layout->setAlignment(Qt::AlignCenter);
    m_layout->update();

    m_isFirstPageHide = false;
}

void EditorWindow::hideFirstPage() {
    m_layout->removeWidget(m_firstWordFrame);
    m_firstWordFrame->setParent(nullptr);
    m_layout->update();
    m_isFirstPageHide = true;
}
void EditorWindow::hideTabWidget() {
    m_layout->removeWidget(m_editorTabMgr);
    m_editorTabMgr->setParent(nullptr);
    showFirstPage();
    m_layout->update();
}

void EditorWindow::showTbaWidget() {
    if (! m_isFirstPageHide) {
        hideFirstPage();
    }
    m_layout->addWidget(m_editorTabMgr);
    m_layout->setAlignment(Qt::AlignCenter);
    m_layout->update();
}

void EditorWindow::addEditPage(hps::EditorBase *editor) {
    // 判断TabWidget是否显示
    if (! m_isFirstPageHide) {
        showTbaWidget();
    }

    // 判断当前文件是否已经打开, 跳转到已经打开的文件
    for (int i = 0; i < m_editorTabMgr->count(); i ++) {
        if (m_editorTabMgr->widget(i) == editor) {
            m_editorTabMgr->setCurrentIndex(i);
            return;
        }
    }

    m_editorTabMgr->addTab(editor, editor->getEditorName());
    m_editorTabMgr->setCurrentIndex(m_editorTabMgr->count() - 1);
}
void EditorWindow::addEditPage(std::string filePath) {
    // 判断TabWidget是否显示
    if (! m_isFirstPageHide) {
        showTbaWidget();
    }
    // 判断当前文件是否已经打开
    for (int i = 0; i < m_editorTabMgr->count(); i ++) {
        hps::EditorBase *editor = (EditorBase *) m_editorTabMgr->widget(i);
        if (editor->getFilePath() == filePath) {
            m_editorTabMgr->setCurrentIndex(i);
            return;
        }
    }

    hps::FileType::Type type = checkFileType(filePath);

    if (type == FileType::markDown) {
        auto markdownEditor = new hps::MarkdownWindow(filePath);
        m_editorTabMgr->addTab(markdownEditor, markdownEditor->getEditorName());
        m_notSaveList.push_back(markdownEditor);
    } else if (type == FileType::cpp) {
        auto editor = new hps::CppWindow(filePath);
        m_editorTabMgr->addTab(editor, editor->getEditorName());
        m_notSaveList.push_back(editor);
    } else if (type == FileType::h) {
        auto editor = new hps::HWindow(filePath);
        m_editorTabMgr->addTab(editor, editor->getEditorName());
        m_notSaveList.push_back(editor);
    } else if (type == FileType::html) {
        auto editor = new hps::HtmlWindow(filePath);
        m_editorTabMgr->addTab(editor, editor->getEditorName());
        m_notSaveList.push_back(editor);
    } else if (type == FileType::xml) {
        auto editor = new hps::XMLWindow(filePath);
        m_editorTabMgr->addTab(editor, editor->getEditorName());
        m_notSaveList.push_back(editor);
    } else if (type == FileType::json) {
        auto editor = new hps::JsonWindow(filePath);
        m_editorTabMgr->addTab(editor, editor->getEditorName());
        m_notSaveList.push_back(editor);
    } else if (type == FileType::pdf) {
        std::string cmd = "google-chrome " + filePath;
        int result = std::system(cmd.c_str());
        if (result != 0) {
            QMessageBox::critical(this, "Error", "open pdf error！");
            std::cerr << "open pdf error! " << __FILE__ << __LINE__ << std::endl;
            return ;
        }
    } else {
        auto editor = new EditorBase(filePath);
        m_editorTabMgr->addTab(editor, editor->getEditorName());
        m_notSaveList.push_back(editor);
    }
    m_editorTabMgr->setCurrentIndex(m_editorTabMgr->count() - 1);
}
void EditorWindow::closeEditTab(int index) {
    auto editor = (hps::EditorBase *) m_editorTabMgr->widget(index);
    // 判断是否已经保存
    if (! isSaveCurFile()) {
        if (QMessageBox::question(this, "提示", "是否保存该文件！", QMessageBox::Yes | QMessageBox::No)
            == QMessageBox::Yes) {
            editor->saveFile();
        }
    }
    m_editorTabMgr->removeTab(index);
    removeSavedFile(editor);
    if (m_editorTabMgr->count() == 0) {
        hideTabWidget();
    }
    delete editor;
}
void EditorWindow::rspFunc() {
    QObject::connect(m_editorTabMgr, &QTabWidget::tabCloseRequested, this, &EditorWindow::closeEditTab);
    QObject::connect(m_tabWidgetMoreButton,
                     &TabWidgetMoreButton::leftButtonClicked,
                     this,
                     &EditorWindow::showTabWidgetMenu);
    QObject::connect(m_setFontSizeAction, &QAction::triggered, this, &EditorWindow::setEditFont);
    QObject::connect(m_closeAllTabAction, &QAction::triggered, this, &EditorWindow::closeAllTab);
    QObject::connect(m_editorTabMgr, &QTabWidget::currentChanged, this, &EditorWindow::getChangePageIndex);
    QObject::connect(m_tabWidgetPreviewButton,
                     &MarkDownPreviewButton::leftButtonClicked,
                     this,
                     &EditorWindow::showMDPreview);
    QObject::connect(m_tabWidgetEditButton, &MarkDownEditButton::leftButtonClicked, this, &EditorWindow::showMDEdit);
    QObject::connect(m_tabWidgetPreviewAndButton,
                     &MarkDownPreviewAndEditButton::leftButtonClicked,
                     this,
                     &EditorWindow::showEditAndPreview);
}
void EditorWindow::keyPressEvent(QKeyEvent *event) {
    if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_S) { // Ctrl + S 保存
        saveCurrentFile();
    } else if (event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_W) {
        int index = m_editorTabMgr->currentIndex();
        closeEditTab(index);
    } else {
        QWidget::keyPressEvent(event); // 调用父类的默认处理方法
    }
}
void EditorWindow::saveCurrentFile() {
    hps::EditorBase *editor = (hps::EditorBase *) m_editorTabMgr->currentWidget();
    editor->saveFile();
    removeSavedFile(editor);
}
bool EditorWindow::isSaveCurFile() {
    if (! m_editorTabMgr->currentWidget()) {
        std::cerr << __FILE__ << ":" << __LINE__ << " no have tabWidget but has check current file is save or not."
                  << std::endl;
        return true;
    }
    auto editor = (hps::EditorBase *) m_editorTabMgr->currentWidget();
    return editor->isFileSave();
}
void EditorWindow::removeSavedFile(EditorBase *editor) {
    for (int i = 0; i < (int) m_notSaveList.size(); i ++) {
        if (m_notSaveList[i] == editor) {
            m_notSaveList.erase(m_notSaveList.begin() + i);
            break;
        }
    }
}
FileType::Type EditorWindow::checkFileType(const std::string &path) {
    int idx = path.size() - 1;
    while (path[idx] != '.') idx --;
    std::string type = path.substr(idx + 1);
    if (type == "md") {
        return FileType::markDown;
    } else if (type == "cpp" || type == "cc" || type == "cu") {
        return FileType::cpp;
    } else if (type == "h") {
        return FileType::h;
    } else if (type == "html") {
        return FileType::html;
    } else if (type == "json") {
        return FileType::json;
    } else if (type == "xml") {
        return FileType::xml;
    } else if (type == "pdf") {
        return FileType::pdf;
    }
    return FileType::unknow;
}
void EditorWindow::showMDPreview() {
    MarkdownWindow *editor = (MarkdownWindow *) m_editorTabMgr->currentWidget();
    editor->showPreview();
    editor->hideTextEdit();
}
void EditorWindow::hideMDPreview() {
    MarkdownWindow *editor = (MarkdownWindow *) m_editorTabMgr->currentWidget();
    editor->hidePreview();
}
void EditorWindow::showTabWidgetMenu() {
    m_tabWidgetMoreMenu->exec(m_tabWidgetMoreButton->mapToGlobal(QPoint(0, m_tabWidgetMoreButton->height())));
}
void EditorWindow::showMDEdit() {
    MarkdownWindow *editor = (MarkdownWindow *) m_editorTabMgr->currentWidget();
    editor->hidePreview();
    editor->showTextEdit();
}
void EditorWindow::hideMDEdit() {
    MarkdownWindow *editor = (MarkdownWindow *) m_editorTabMgr->currentWidget();

    editor->getEditText()->hide();
}
void EditorWindow::setEditFont() {
    // 获取输入的字体
    bool ok;
    int fontSize = QInputDialog::getInt(this,
                                        "输入",
                                        "请输入字体大小：",
                                        CONFIG()->getNoteBookCfg().EditorTextFontSize,
                                        10,
                                        20,
                                        1,
                                        &ok);
    if (! ok) {
        QMessageBox::critical(this, "Error", "Input not a Int!");
        return;
    }

    auto editor = (EditorBase *) m_editorTabMgr->currentWidget();
    auto editorTextEdit = editor->getEditText();
    CONFIG()->setEditorTextPointSize(fontSize);
    editorTextEdit->setFont(CONFIG()->getEditorTextEditFont());
    editorTextEdit->update();
}
void EditorWindow::closeAllTab() {
    // 创建一个询问对话框
    QMessageBox msgBox(this);
    msgBox.setWindowTitle("提示");
    msgBox.setText("有文件尚未保存！");

    // 自定义按钮文本
    QPushButton *yesButton = msgBox.addButton("保存并关闭", QMessageBox::YesRole);
    QPushButton *noButton = msgBox.addButton("不保存退出", QMessageBox::NoRole);
    QPushButton *cancelButton = msgBox.addButton("取消", QMessageBox::RejectRole);

    // 设置默认按钮
    msgBox.setDefaultButton(cancelButton);

    if (! m_notSaveList.empty()) {
        msgBox.exec();
    } else { //  没有未保存的文件，全部关闭
        for (int i = 0; i < (int) m_editorTabMgr->count(); i ++) {
            closeEditTab(0);
        }
    }

    // 根据用户的选择结果执行相应的操作
    if (msgBox.clickedButton() == yesButton) {
        for (int i = 0; i < m_editorTabMgr->count(); i ++) {
            auto editor = (EditorBase *) m_editorTabMgr->widget(i);
            editor->saveFile();
        }
        for (int i = 0; i < m_editorTabMgr->count(); i ++) {
            auto editor = (EditorBase *) m_editorTabMgr->widget(i);
            m_editorTabMgr->removeTab(i);
            delete editor;
        }
        hideTabWidget();
    } else if (msgBox.clickedButton() == noButton) {
        for (int i = 0; i < m_editorTabMgr->count(); i ++) {
            auto editor = m_editorTabMgr->widget(i);
            m_editorTabMgr->removeTab(i);
            delete editor;
        }
        hideTabWidget();
    } else if (msgBox.clickedButton() == cancelButton) {
        return;
    }

}
bool EditorWindow::isShowMarkDownButtons(EditorBase *editor) {
    FileType::Type fileType = checkFileType(editor->getFilePath());
    bool res = false;
    if (FileType::markDown == fileType)
        res = true;
    return res;
}
void EditorWindow::showMarkDownButtons() {
    m_tabWidgetEditButton->show();
    m_tabWidgetPreviewButton->show();
    m_tabWidgetPreviewAndButton->show();
    m_tabWidgetButtonsLayout->update();
}
void EditorWindow::hideMarkDownButtons() {
    m_tabWidgetEditButton->hide();
    m_tabWidgetPreviewButton->hide();
    m_tabWidgetPreviewAndButton->hide();
    m_tabWidgetButtonsLayout->update();
}
void EditorWindow::getChangePageIndex(int index) {
    if (index == -1) { // 当前没有正在打开的编辑框
        return ;
    }
    auto editor = (EditorBase *) m_editorTabMgr->widget(index);
    if (isShowMarkDownButtons(editor)) {
        showMarkDownButtons();
    } else {
        hideMarkDownButtons();
    }
}
void EditorWindow::showEditAndPreview() {
    auto editor = (MarkdownWindow*) m_editorTabMgr -> currentWidget();
    editor -> showPreviewAndTextEdit();
}

} // hps